﻿using System;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace DotnetUtil.GZip
{
    public static class GZipHelper
    {
        #region 压缩方法

        /// <summary>
        /// 使用GZip算法压缩字符串
        /// </summary>
        /// <param name="rawString">需要压缩的字符串</param>
        /// <returns>压缩后的Base64编码的字符串</returns>
        public static string GZipCompressString(string rawString)
        {
            if (string.IsNullOrEmpty(rawString))
            {
                return string.Empty;
            }

            var rawData = Encoding.UTF8.GetBytes(rawString);
            var zippedData = GZipCompress(rawData);
            return Convert.ToBase64String(zippedData);
        }

        /// <summary>
        /// GZip压缩
        /// </summary>
        /// <param name="rawData">原始字节数组</param>
        /// <returns>GZip压缩后的字节数组</returns>
        private static byte[] GZipCompress(byte[] rawData)
        {
#if NET6_0_OR_GREATER
            using var stream = new MemoryStream();
            using (var zipStream = new GZipStream(stream, CompressionMode.Compress, true))
            {
                zipStream.Write(rawData, 0, rawData.Length);
            }

            return stream.ToArray();
#else
            using (var stream = new MemoryStream())
            {
                using (var zipStream = new GZipStream(stream, CompressionMode.Compress, true))
                {
                    zipStream.Write(rawData, 0, rawData.Length);
                }

                return stream.ToArray();
            }
#endif
        }

        #endregion

        #region 解压方法

        /// <summary>
        /// GZip算法解压缩字符串
        /// </summary>
        /// <param name="compressedString">GZip压缩后的字符串</param>
        /// <returns>解压后的字符串</returns>
        public static string GZipDecompressString(string compressedString)
        {
            if (string.IsNullOrEmpty(compressedString))
            {
                return string.Empty;
            }

            var zippedData = Convert.FromBase64String(compressedString);
            var rawData = GZipDecompress(zippedData);
            return Encoding.UTF8.GetString(rawData);
        }

        /// <summary>
        /// Zip解压
        /// </summary>
        /// <param name="zippedData">GZip压缩后的字节数组</param>
        /// <returns>原始字节数组</returns>
        private static byte[] GZipDecompress(byte[] zippedData)
        {
#if NET6_0_OR_GREATER
            using var inStream = new MemoryStream(zippedData);
            using var zipStream = new GZipStream(inStream, CompressionMode.Decompress);
            using var outStream = new MemoryStream();
            var block = new byte[1024];
            while (true)
            {
                var bytesRead = zipStream.Read(block, 0, block.Length);
                if (bytesRead <= 0)
                {
                    break;
                }

                outStream.Write(block, 0, bytesRead);
            }

            return outStream.ToArray();
#else
            using (var inStream = new MemoryStream(zippedData))
            {
                using (var zipStream = new GZipStream(inStream, CompressionMode.Decompress))
                {
                    using (var outStream = new MemoryStream())
                    {
                        var block = new byte[1024];
                        while (true)
                        {
                            var bytesRead = zipStream.Read(block, 0, block.Length);
                            if (bytesRead <= 0)
                            {
                                break;
                            }

                            outStream.Write(block, 0, bytesRead);
                        }

                        return outStream.ToArray();
                    }
                }
            }
#endif
        }
        #endregion
    }
}
